/**
*
*   服务端开发，发送客户端发送制定的数据，服务端反馈
*   因为有：： 命名空间所以需要g++ 编译
*
*
**/


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

/* For inet_ntoa. */
#include <arpa/inet.h>
/* Required by event.h. */
#include <sys/time.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <err.h>


#include<event.h>
#include <evutil.h>

#define SERVER_PORT 65533

void socket_read_cb(int fd , short events, void *arg)
{
    char msg[4096];
    struct event *ev = (struct event *)arg;
    int len = read(fd , msg , sizeof(msg)-1);
    msg[len] = '\0';
    printf(" recv the client msg is %s",msg);
    char replay_msg[4096] = " I have recvieved the msg : ";
    strcat(replay_msg +strlen(replay_msg) , msg);
    write(fd , replay_msg , strlen(replay_msg));
}

void accept_cb(int fd, short events , void *arg){
    evutil_socket_t sockfd ;
    struct sockaddr_in client;
    socklen_t len;

    sockfd = ::accept(fd ,(struct sockaddr*)&client , &len );
    evutil_make_socket_nonblocking(sockfd);
    struct event_base *base = (event_base *)arg;
    struct event *ev = event_new (NULL, -1, 0 ,NULL,NULL);
    event_assign(ev, base , sockfd , EV_READ |EV_PERSIST , socket_read_cb ,  (void *)ev);
    event_add(ev, NULL);
}



int main()
{

    evutil_socket_t listener;
    listener  = ::socket(AF_INET , SOCK_STREAM ,0);
  //  evutil_make_socket_nonblocking(listener);
    listener =socket(AF_INET,SOCK_STREAM ,IPPROTO_TCP);
    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family= AF_INET;
    server.sin_addr.s_addr=htonl(INADDR_ANY);
    server.sin_port=htons(SERVER_PORT);

    if(::bind(listener,(sockaddr *)&server, sizeof(server)) < 0 )
        exit(-1);

    if(::listen(listener , 10) < 0)
        exit(-1);

      evutil_make_socket_nonblocking(listener);

      struct event_base *base = event_base_new();
      struct event *ev_listen = event_new(base ,listener ,EV_READ |EV_PERSIST , accept_cb,base );
      event_add(ev_listen , NULL);
      event_base_dispatch(base);
}
